package org.example.springboot.controller;

import cn.hutool.core.io.FileUtil;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.example.springboot.common.Result;
import org.example.springboot.exception.CustomException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 处理文件上传和下载的控制器
 */
@RestController
@RequestMapping("/files")
public class FileController {
    // 文件上传的路径，使用系统属性获取项目根路径并拼接"files/"作为存储目录
    private static final String filePath = System.getProperty("user.dir") + "/files/";

    /**
     * 文件上传接口
     *
     * @param file 前端上传的文件，通过 MultipartFile 类型接收
     * @return 返回上传结果，包括文件名和访问路径等信息
     * @throws IOException 文件上传过程中可能发生的 I/O 异常
     */
    @PostMapping("/upload")
    public Result upload(MultipartFile file) throws IOException {
        // 获取上传文件的原始名称
        String originalFilename = file.getOriginalFilename();
        // 检查并创建上传目录
        if (!FileUtil.isDirectory(filePath)) {
            FileUtil.mkdir(filePath); // 创建一个files目录
        }
        // 为文件名加一个唯一的表示，防止重名
        String fileName = System.currentTimeMillis() + "_" + originalFilename;
        // 拼接完整的文件路径
        String realPath = filePath + fileName;
        try {
            // 将文件写入指定路径
            FileUtil.writeBytes(file.getBytes(), realPath);
        } catch (IOException e) {
            // 处理文件上传失败的异常
            e.printStackTrace();
            throw new CustomException("500", "文件上传失败");
        }
        String url = "http://localhost:9090/files/download/" + fileName;
        // 返回文件上传成功的响应
        return Result.success(url);
    }

    /**
     * 文件下载接口
     *
     * @param fileName 要下载的文件名，通过 URL 路径变量传递
     * @param response 用于输出文件流的 HTTP 响应对象
     * @throws IOException 文件下载过程中可能发生的 I/O 异常
     */
    /**
 * 文件下载接口
 *
 * @param fileName 要下载的文件名（从 URL 路径中获取）
 * @param response HttpServletResponse 用于向客户端输出文件流
 */
    @GetMapping("/download/{fileName}")
    public void download(@PathVariable String fileName, HttpServletResponse response) {
        try {
            // 设置响应头，告诉浏览器这是一个附件（即触发下载行为）
            // 使用 URLEncoder 对文件名进行编码，防止中文文件名乱码
            response.addHeader("Content-Disposition", "attachment;filename=" +
                    URLEncoder.encode(fileName, StandardCharsets.UTF_8));

            // 设置响应内容类型为二进制流，适用于任意类型的文件
            response.setContentType("application/octet-stream");

            // 获取 ServletOutputStream，用于将文件数据写入 HTTP 响应输出流
            ServletOutputStream outputStream = response.getOutputStream();

            // 使用 Hutool 工具类读取指定路径下的文件为字节数组
            byte[] fileBytes = FileUtil.readBytes(filePath + fileName);

            // 将文件字节数据写入输出流，供浏览器下载
            outputStream.write(fileBytes);

            // 刷新缓冲区，确保数据全部写出
            outputStream.flush();

            // 关闭输出流，释放资源
            outputStream.close();
        } catch (IOException e) {
            // 如果发生 IO 异常，抛出自定义异常并提示“文件下载失败”
            throw new CustomException("500", "文件下载失败");
        }
    }


 /**
 * 专为富文本编辑器（如 wangEditor）设计的文件上传接口
 *
 * @param file 前端上传的文件，通过 MultipartFile 类型接收
 * @return 返回符合 wangEditor 要求的数据结构
 */
    @PostMapping("/wang/upload")
    public Map<String, Object> wangEditorUpload(MultipartFile file) {
        // 获取上传文件的原始名称（带扩展名）
        String originalFilename = file.getOriginalFilename();

        // 检查指定路径是否存在，不存在则创建目录
        if (!FileUtil.isDirectory(filePath)) {
            FileUtil.mkdir(filePath); // 创建一个名为 "files" 的目录用于存储上传文件
        }

        // 使用时间戳 + 原始文件名的方式生成唯一文件名，防止重名
        String fileName = System.currentTimeMillis() + "_" + originalFilename;

        // 拼接完整的文件保存路径
        String realPath = filePath + fileName;

        try {
            // 将上传的文件内容写入服务器本地磁盘
            FileUtil.writeBytes(file.getBytes(), realPath);
        } catch (IOException e) {
            // 如果写入失败，抛出自定义异常并提示“文件上传失败”
            e.printStackTrace();
            throw new CustomException("500", "文件上传失败");
        }

        // 构建返回给前端的访问 URL
        String url = "http://localhost:9090/files/download/" + fileName;

        // 构建符合 wangEditor 要求的响应数据结构
        Map<String, Object> resMap = new HashMap<>();

        // 创建一个 List 存储多个文件信息（虽然只传了一个文件，但 wangEditor 支持多文件）
        List<Map<String, Object>> list = new ArrayList<>();

        // 创建单个文件的 map，包含访问 URL
        Map<String, Object> urlMap = new HashMap<>();
        urlMap.put("url", url); // 设置文件访问地址

        // 添加到列表中
        list.add(urlMap);

        // 设置返回结果：errno 为 0 表示成功
        resMap.put("errno", 0);
        // 设置返回数据（文件列表）
        resMap.put("data", list);

        // 返回最终结果给前端
        return resMap;
    }


}
